#include "globals.fxh"

	// TODO
	float g_SpecularPower = 300;
	float g_SpecularMaterialFactor = 0.2;
	float g_DiffuseMaterialFactor = 0.8;
	float4 g_AmbientLight = {0.1, 0.1, 0.1, 1.0};
	//float4 g_AmbientLight = {0.0, 0.0, 0.0, 1.0};
	//float g_Intensity = 1; //Tiene que ser un vector de 4, cada luz tiene su intensidad!

float3 GetPositionFromZDepthViewInViewCoordinates(float ZDepthView, float2 UV, float4x4 InverseProjectionMatrix) 
{
	// Get the depth value for this pixel
	// Get x/w and y/w from the viewport position
	float x = UV.x * 2 - 1;
	float y = (1 - UV.y) * 2 - 1;
	float4 l_ProjectedPos = float4(x, y, ZDepthView, 1.0);
	// Transform by the inverse projection matrix
	float4 l_PositionVS = mul(l_ProjectedPos, InverseProjectionMatrix);
	// Divide by w to get the view-space position
	return l_PositionVS.xyz / l_PositionVS.w;
}	

float3 GetPositionFromZDepthView(float ZDepthView, float2 UV, float4x4 InverseViewMatrix, float4x4 InverseProjectionMatrix)
{
	float3 l_PositionView=GetPositionFromZDepthViewInViewCoordinates(ZDepthView, UV, InverseProjectionMatrix);
	return mul(float4(l_PositionView,1.0), InverseViewMatrix).xyz;
}

float3 Normal2Texture(float3 Normal)
{
	return Normal*0.5+0.5;
}
	
	
float3 GetOmniContrib(float3 WorldPosition, float3 WorldNormal, int i)
{

	float3 l_LightDir = WorldPosition-g_LightsPosition[i];
	float3 l_NormalizedLightDir = l_LightDir/length(l_LightDir);
	float l_DistAtt = 1 - saturate((length(l_LightDir) - g_LightsStartRangeAttenuation[i])/(g_LightsEndRangeAttenuation[i] - g_LightsStartRangeAttenuation[i]));

	float3 Nn=normalize(WorldNormal);
	
	//Diffuse
    float l_DiffuseContrib=saturate(dot(Nn, -l_NormalizedLightDir));
	float3 l_DiffuseLightColor = g_LightsColor[i]*l_DiffuseContrib*l_DistAtt*g_DiffuseMaterialFactor*g_LightsIntensity[i];

	//Specular
    
    float3 Hn=normalize(normalize(g_CameraPosition-WorldPosition)-l_NormalizedLightDir);
    float l_SpecularContrib=pow(saturate(dot(Hn, Nn)), g_SpecularPower)*l_DiffuseContrib;
    float3 l_SpecularLighting=l_SpecularContrib*g_LightsColor[i]*l_DistAtt*g_SpecularMaterialFactor*g_LightsIntensity[i];

	
	//Total
    float3 l_TotalColor=l_DiffuseLightColor+l_SpecularLighting;
	return l_TotalColor;

}

float3 GetDirectionalContrib(float3 WorldPosition, float3 WorldNormal, int i)
{
	float3 Nn=normalize(WorldNormal);
    float3 Hn=normalize(normalize(g_CameraPosition-WorldPosition)-g_LightsDirection[i]);
	
		//Diffuse
    float l_DiffuseContrib=saturate(dot(Nn, -g_LightsDirection[i]));
	float3 l_DiffuseLightColor = g_LightsColor[0]*l_DiffuseContrib*g_DiffuseMaterialFactor*g_LightsIntensity[i];
	
	//Specular
    float l_SpecularContrib=pow(saturate(dot(Hn, Nn)), g_SpecularPower) * l_DiffuseContrib;
    float3 l_SpecularLighting=l_SpecularContrib*g_LightsColor[i]*g_SpecularMaterialFactor*g_LightsIntensity[i];


	//Total
    float3 l_TotalColor=l_DiffuseLightColor+l_SpecularLighting;
	return l_TotalColor;
}

float3 GetSpotContrib(float3 WorldPosition, float3 WorldNormal, int i)
{
	float3 l_LightDir = WorldPosition-g_LightsPosition[i];
	float3 l_NormalizedLightDir = l_LightDir/length(l_LightDir);
	float3 Nn=normalize(WorldNormal);
	float l_DistAtt = 1 - saturate((cos(g_LightsAngle[i]/2) - dot(l_NormalizedLightDir, g_LightsDirection[i]))/(cos(g_LightsAngle[i]/2) - cos(g_LightsFallOff[i]/2)));
	
	//Diffuse
    float l_DiffuseContrib=saturate(dot(Nn, -l_NormalizedLightDir));
	float3 l_DiffuseLightColor = g_LightsColor[i]*l_DiffuseContrib*l_DistAtt*g_DiffuseMaterialFactor*g_LightsIntensity[i];
	
	//Specular
    float3 Hn=normalize(normalize(g_CameraPosition-WorldPosition)-l_NormalizedLightDir);
    float l_SpecularContrib=pow(saturate(dot(Hn, Nn)), g_SpecularPower) * l_DiffuseContrib;
    float3 l_SpecularLighting=l_SpecularContrib*g_LightsColor[i]*l_DistAtt*g_SpecularMaterialFactor*g_LightsIntensity[i];

	

	//Total
    float3 l_TotalColor=l_DiffuseLightColor+l_SpecularLighting;
	return l_TotalColor;
}

float4 CalcLighting (float3 WorldPosition, float3 WorldNormal, float4 DiffuseColor)
{
	int i = 0;
	float3 l_TotalContrib = float3(0.0, 0.0, 0.0);
	for (i=0; i<MAX_LIGHTS; ++i)
	{
		
		if(g_LightsEnabled[i])
		{
			if(g_LightsType[i] == 0)
			{
				l_TotalContrib = l_TotalContrib + GetOmniContrib(WorldPosition, WorldNormal, i);
			}
			else if(g_LightsType[i] == 1)
			{
				l_TotalContrib = l_TotalContrib + GetDirectionalContrib(WorldPosition, WorldNormal, i);
			}
			else if(g_LightsType[i] == 2)
			{
				
				l_TotalContrib = l_TotalContrib + GetSpotContrib(WorldPosition, WorldNormal, i);
			}
		
		}
		
	}
	
	 l_TotalContrib = l_TotalContrib + g_AmbientLight;
	
	return DiffuseColor  *float4(l_TotalContrib ,1);
}



float3 Texture2Normal(float3 Color)
{
	return (Color-0.5)*2;
}


float4 CalcLightingDeferred (float3 WorldPosition, float3 WorldNormal, float4 DiffuseColor)
{
	float3 l_TotalContrib = float3(0.0, 0.0, 0.0);
	
	if(g_LightsEnabled[0])
	{
		if(g_LightsType[0] == 0)
		{
			l_TotalContrib = l_TotalContrib + GetOmniContrib(WorldPosition, WorldNormal, 0);
		}
		else if(g_LightsType[0] == 1)
		{
			l_TotalContrib = l_TotalContrib + GetDirectionalContrib(WorldPosition, WorldNormal, 0);
		}
		else if(g_LightsType[0] == 2)
		{
			l_TotalContrib = l_TotalContrib + GetSpotContrib(WorldPosition, WorldNormal, 0);
		}
		
	}
	
	return DiffuseColor*float4(l_TotalContrib ,1);
}


float3 CalcAnimtedPos(float4 Position, float4 Indices, float4 Weight)
{
	float3 l_Position=0;
	l_Position = mul(g_Bones[Indices.x], Position) * Weight.x;
	l_Position += mul(g_Bones[Indices.y], Position) * Weight.y;
	l_Position += mul(g_Bones[Indices.z], Position) * Weight.z;
	l_Position += mul(g_Bones[Indices.w], Position) * Weight.w;
	return l_Position;
}
void CalcAnimatedNormalTangent(float3 Normal, float3 Tangent, float4 Indices, float4 Weight, out float3 OutNormal, out float3 OutTangent)
{
	OutNormal = 0;
	OutTangent =0;
	float3x3 m;
	m[0].xyz = g_Bones[Indices.x][0].xyz;
	m[1].xyz = g_Bones[Indices.x][1].xyz;
	m[2].xyz = g_Bones[Indices.x][2].xyz;
	OutNormal += mul(m, Normal.xyz)* Weight.x;
	OutTangent += mul(m, Tangent.xyz)* Weight.x;
	m[0].xyz = g_Bones[Indices.y][0].xyz;
	m[1].xyz = g_Bones[Indices.y][1].xyz;
	m[2].xyz = g_Bones[Indices.y][2].xyz;
	OutNormal += mul(m, Normal.xyz)* Weight.y;
	OutTangent += mul(m, Tangent.xyz)* Weight.y;
	m[0].xyz = g_Bones[Indices.z][0].xyz;
	m[1].xyz = g_Bones[Indices.z][1].xyz;
	m[2].xyz = g_Bones[Indices.z][2].xyz;
	OutNormal += mul(m, Normal.xyz)* Weight.z;
	OutTangent += mul(m, Tangent.xyz)* Weight.z;
	m[0].xyz = g_Bones[Indices.w][0].xyz;
	m[1].xyz = g_Bones[Indices.w][1].xyz;
	m[2].xyz = g_Bones[Indices.w][2].xyz;
	OutNormal += mul(m, Normal.xyz)* Weight.w;
	OutTangent += mul(m, Tangent.xyz)* Weight.w;
	OutNormal = normalize(OutNormal);
	OutTangent = normalize(OutTangent);
}